home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / packet / p_tapr / tnchst / dlc.c < prev    next >
Text File  |  1992-03-16  |  13KB  |  439 lines

  1. /***** DATA LINK CONTROL PROTOCOL   SOFTWARE (c) 1990-91 Howard Goldstein ***/
  2. /* all rights reserved.  permission for non-commercial amateur use
  3. /* granted */
  4.  
  5. #include   "dlc.inc"
  6.  
  7.     /*** global variables ***/
  8.  
  9.                     /* storage for dlc control blocks */
  10.     struct    dlccb_struct    dlcbs;
  11.  
  12.  
  13.     byte    calling_addr    ;    /* set in AFT_IN_H, reflects calling
  14.                                    addr of the last dlc frame rcvd */
  15.     extern    byte mydlcnum ;        /* this computer's DLC address */
  16.  
  17.  
  18. void cdecl dlc_init()                /* call on init */
  19. {
  20.         dlcbs.dlc_state = DLIDLE ; /* state to idle */
  21.         dlcbs.timer   = (-1)   ;    /* stop timer */
  22.         dlcbs.dlc_peer_addr = DEFAULT_DLC_PEER ; /* addr to call when we
  23.                                                     initiate the dlc link */
  24. }
  25.  
  26.  
  27.     /* set timer to expired and zero the retry counter - called on
  28.        state change */
  29. void cdecl  dlc_timer_retry_reset( dlccb )
  30. struct dlccb_struct *dlccb;
  31. {
  32.     dlccb->timer = 0 ;        /* causes immediate expiration */
  33.     dlccb->retry_count = 0 ;
  34. }
  35.  
  36. void cdecl dlc_event( event, dlccb, bframe, len)
  37. byte  event;        /* as defined by preproc directives */
  38. struct dlccb_struct *  dlccb;
  39. struct dlc_frame_struct *  bframe;    /* ptr to frame, if any associated w/ event */
  40. word  len;            /* len "    " */
  41. {
  42.     byte    nstate;
  43.             /* these are the state tables; included later, must
  44.                be identified here */
  45.     extern    struct dlc_state_entry dlcs_table[][DNEVENTS];
  46.  
  47.     void    (*hdlr) (struct dlccb_struct *, struct dlc_frame_struct *,
  48.              word );
  49.  
  50.  
  51.             /* set up local vars w/ results of lookup */
  52.         nstate = dlcs_table[dlccb->dlc_state - 1][event].newstate ;
  53.         hdlr = dlcs_table[dlccb->dlc_state - 1][event].action_handler ;
  54.  
  55. #if DLC_EVENT_TRACE
  56.       printf("dlc event %d old state %d new state %d\n",event,dlccb->dlc_state,
  57.                nstate);
  58. #endif
  59.  
  60.                 /* if new state is mentioned and diff from the
  61.                    current state */
  62.         if ( nstate && nstate != dlccb->dlc_state)
  63.         {
  64.             dlc_timer_retry_reset( dlccb );    /* reset timer, try */
  65.             dlccb->dlc_state = nstate ;    /* change state */
  66.         }
  67.  
  68.         if ( hdlr )    /* if a handler was defined */
  69.             (*hdlr) (dlccb,bframe,len) ;    /* then run it */
  70.  
  71. }
  72.  
  73.     /* call on timer tick intervals - updates and signals expiration
  74.        events */
  75. void cdecl  dlc_timer_tick()
  76. {
  77.     byte    x;
  78.  
  79.         if ( dlcbs.dlc_state != DLIDLE     /* if not idle and */
  80.           && dlcbs.timer >= 0 )        /* timer not stopped */
  81.         {                /* then count time pd - */
  82.             if ( ( --dlcbs.timer < 1 ) ) /* if now expired */
  83.             {                /*   then signal event*/
  84.  
  85.                 /* force timer to stay expired */
  86.               --dlcbs.timer ;
  87.  
  88.                 /* count retry */
  89.               if ( dlcbs.retry_count++ == DLC_MAX_TRIES )
  90.                     /* if retry lim excdd then LRETRY event*/
  91.                 dlc_event( D_RETRYX, &dlcbs, NULL, 0 );
  92.               else
  93.                                  /* else TIMER event, */
  94.                         /* type event depends on
  95.                            whether in supvy state or
  96.                            not */
  97.                   dlc_event( D_TIMERX, &dlcbs, NULL, 0 );
  98.             }
  99.         }
  100. }
  101.  
  102.  
  103.             /* initialize dlccb data machine, ptrs etc */
  104. void cdecl  dlc_data_init( dlccb )
  105. struct dlccb_struct *dlccb;
  106. {
  107.     dlccb->dlctxseq = dlccb->dlcrxseq = dlccb->outstanding = 0 ;
  108.         dlccb->dl_next.next = NULL ;        /* clr linked list ptr */
  109. }
  110.  
  111.  
  112. void cdecl  send_dlc_fr( dlccb, dlc_cmd, info, len)
  113. struct dlccb_struct *dlccb;
  114. byte dlc_cmd ;            /* cmd byte */
  115. byte *info;
  116. word len;
  117. {
  118.         struct    itm_struct    *itm ;        /* aft sender eats itms */
  119.     byte    *insertptr ;            /* ptr to insert data */
  120.     int    retval ;            /* holds success value to return
  121.                            when allocated an itm ok */
  122.  
  123.         /* allocate an intertask msg - if couldnt allcoate */
  124.     if ( ! (itm = (struct itm_struct *)
  125.             malloc(AFTMAXFRAMESIZE + sizeof( struct itm_struct ) ) ) )
  126.          ;        /*then do nothing */
  127.     else /* else was able to allocate, no problem */
  128.     {
  129.  
  130.         itm->msg_len = len+1 ;        /* length is size of data +
  131.                            size of no-addrs header */
  132.  
  133.         insertptr = itm->itm_data ;    /* pointer we'll bld packet to */
  134.  
  135.         if ( mydlcnum )     /* if we have a dlc address then  */
  136.         {            /* need to stuff the addresses */
  137.             *insertptr++ = dlccb->dlc_peer_addr ;    /* stuff dest*/
  138.             *insertptr++ = mydlcnum ;    /* stuff ours (src)*/
  139.             
  140.             itm->msg_len += 2 ;        /* adj size for the
  141.                                2 addr bytes */
  142.         } 
  143.  
  144.         *insertptr++ = dlc_cmd ;    /* insert cmd byte */
  145.         memcpy( insertptr, info, len ) ;    /* move data */
  146.  
  147.         aftt_send( itm );    /* now try to send the frame */
  148.                 free( (char *) itm );            /* and free it once it's done */
  149.     }
  150. }
  151.  
  152.  
  153. void cdecl  send_resetack(dlccb, bframe, len)
  154. struct dlccb_struct *dlccb;
  155. struct dlc_frame_struct *bframe;
  156. word len;
  157. {
  158.     send_dlc_fr( dlccb, 0x20, NULL, 0);
  159. }
  160.  
  161. void cdecl  send_dlcdack(dlccb,bframe,len)
  162. struct dlccb_struct *dlccb;
  163. struct dlc_frame_struct *bframe;
  164. word len;
  165. {
  166.     send_dlc_fr( dlccb, 0x50 + dlccb->dlcrxseq, NULL, 0);
  167. }
  168.  
  169. void cdecl  dlc_ring_in(dlccb, bframe, len )
  170. struct dlccb_struct *dlccb;
  171. struct dlc_frame_struct *bframe;
  172. word len;
  173. {
  174.  
  175.     dlc_data_init( dlccb );        /* init data */
  176.     dlccb->dlc_state = DLDATA;    /* indicate state is data - all rdy to go */
  177.     dlccb->dlc_peer_addr = calling_addr ;    /* stuff the calling dlc's addr */
  178.     send_resetack( dlccb, NULL, 0);
  179.                                 /* and ack the reset */
  180. }
  181.  
  182.     /* estabs outgoing */
  183. void cdecl    dlc_ring_out(dlccb, bframe, len)
  184. struct dlccb_struct *dlccb;
  185. struct dlc_frame_struct *bframe;
  186. word len;
  187. {
  188.     dlc_data_init(dlccb);        /* init data is all tts required. state
  189.                                    table takes care of timers etc */
  190. }
  191.  
  192. void cdecl  dlc_retryfail(dlccb, bframe, len)
  193. struct dlccb_struct *dlccb;
  194. struct dlc_frame_struct *bframe;
  195. word len;
  196. {
  197.     dlccb->retry_count = 0 ;    /** FOREVER RETRY **/
  198. }
  199.  
  200. void cdecl  dlc_retryreset(dlccb, bframe, len)
  201. struct dlccb_struct *dlccb;
  202. struct dlc_frame_struct *bframe;
  203. word len;
  204. {
  205.     send_dlc_fr( dlccb, 0x10, NULL, 0 );
  206.     dlccb->timer = DLC_RETRY_TIME ;
  207. }
  208.  
  209. void cdecl  dlc_senddata(dlccb, bframe, len)
  210. struct dlccb_struct *dlccb;
  211. struct dlc_frame_struct *bframe;
  212. word len;
  213. {
  214.     byte    ts;        /* transmit sequence # holder */
  215.     struct    dl_data_struct *pkt ;    /* point to data to send */
  216.  
  217.     ts = dlccb->dlctxseq ;            /* starting tx seq # */
  218.  
  219.     pkt = &dlccb->dl_next ;        /* points to oldest outstand
  220.                         ing packet, if !null */
  221.  
  222.         /* now traverse the linked list of pktzd xmit data */
  223.     while ( pkt->next )        /* while pkt in the list */
  224.     {
  225.         pkt = pkt->next ;        /* traverse to next pkt */
  226.                 /* send the packet */
  227.         send_dlc_fr( dlccb, 0x40 + ts, pkt->data, pkt->len );
  228.         ts = ( ( ts+1 ) & 15 );        /* next seq #, mod 16 */
  229.     }
  230.      /*endwhile */
  231.  
  232.     dlccb->timer = DLC_RETRY_TIME ;        /* restart timer */
  233.  
  234. }
  235.  
  236. void cdecl  dlc_dataproc(dlccb, bframe, len)
  237. struct dlccb_struct *dlccb;
  238. struct dlc_frame_struct *bframe;
  239. word len;
  240. {
  241.     if ( (bframe->cmd & 15) == dlccb->dlcrxseq )    /* if seq # matches */
  242.     {
  243.         if ( dlc_data_handler( bframe->data,
  244.                     len-1 ) )    /* if upper level
  245.                                 toook the frame */
  246.         {
  247.                  /* mod16 bump*/
  248.             dlccb->dlcrxseq = ( (dlccb->dlcrxseq+1) & 15 );
  249.             send_dlcdack( dlccb, NULL, 0 );    /*then send ack, */
  250.         }
  251.         else /* upper level could not take the frame */
  252. /*            send_dbusy( dlccb, NULL, 0 );    /* send busy */
  253.             send_dlcdack( dlccb, NULL, 0 );    /* send busy */
  254.     }
  255.     else  /* else seq # didnt match */
  256.         send_dlcdack( dlccb, NULL,0 );    /* send what we do hv */
  257. }
  258.  
  259. void cdecl  dlc_ackproc(dlccb, bframe, len)
  260. struct dlccb_struct *dlccb;
  261. struct dlc_frame_struct *bframe;
  262. word len;
  263. {
  264.     byte    ackseq, nacked;        /* remote acks to seq ackseq, nacked
  265.                        # of packets */
  266.     struct    dl_data_struct *ptr;       /* use to delete packets from
  267.                     head of linked list */
  268.  
  269.     dlccb->retry_count = 0        ;     /* reset retry count */
  270.     
  271.     ackseq = ( bframe->cmd & 15 ) ;    /* strip off seq #, mod 16 */
  272.  
  273.     nacked = ( ackseq - dlccb->dlctxseq ) & 15 ;    /* he acks this many */
  274.  
  275.     if ( nacked > dlccb->outstanding )        /* if too many */
  276.         printf("*** error- too many acked\n");    /* need to do error!*/
  277.     else /* else no problem */
  278.     {
  279.       if ( dlccb->outstanding > 0 )        /* if packets were outsdng */
  280.       {
  281.         dlccb->dlctxseq = ackseq ;        /* update tx seq # */
  282.  
  283.         if ( (dlccb->outstanding-=nacked) == 0 )    /* if all ackd */
  284.         dlc_event( D_ALL_ACK, dlccb, NULL, 0) ;    /* then gen event */
  285.  
  286.             while ( nacked-- )        /* while packets left to release */
  287.         {
  288.         ptr = dlccb->dl_next.next->next ;
  289.                     /* link to 2d packet */
  290.  
  291.         free( (char *) dlccb->dl_next.next );    /* free 1st packet */
  292.         dlccb->dl_next.next = ptr ;    /* make 2d pkt the 1st in the
  293.                            head record */
  294.         } /*endwhile packets left to release*/
  295.        } /*endif outstanding packets */
  296.     } /*endif else */
  297. }
  298.  
  299.  
  300.       /** called from underlying AFT receiver **/
  301.     /** converts AFT frames into events and runs the event handler **/
  302. void cdecl  aft_in_handler( bframe, len )
  303. struct dlc_frame_struct *bframe;
  304. word len;
  305. {
  306.     byte    event ;        /* will convert dlc cmd to event */
  307.     byte    dest ;    /* temp holders for dlc source and dest vals*/
  308.     int    x ;
  309.     struct dlccb_struct *dlccb ;
  310.  
  311.         /* do (conditional) address checking */
  312.     if ( mydlcnum )        /* check addresses? only if set */
  313.     {
  314.         dest = bframe->cmd ;    /* load up the misplaced addr holders */
  315.         calling_addr = bframe->data[0] ;
  316.  
  317.                 /* if dest addr doesnt match */
  318.         if ( dest != mydlcnum && dest != GLOBALDLC )
  319.             return ;    /* then return/ DROP THE PACKET ON
  320.                         THE FLOOR */
  321.             /* else we should process it - first gotta remove
  322.                the address fields from this pseudo-union */
  323.         len -= 2 ;    /* remove addr bytes from len */
  324.  
  325.                 /* and use inefficient move */
  326.         memcpy( (char *) bframe, (char *) bframe + 2 , len );
  327.     } /* endif addr check */
  328.         
  329.         /* force the dlccb for this lcn */
  330.     dlccb = &dlcbs;
  331.  
  332.  
  333.     if ( dlccb->dlc_state == DLIDLE )        /* if not connected */
  334.         switch( bframe->cmd )    /* then what kind of cmd? */
  335.         {
  336.             case 0x10:
  337.                     /* kluge to get around need
  338.                        to know dlccb in event tables */
  339.                 dlc_ring_in( NULL, bframe, len );
  340.                 break ;
  341.             default:
  342.                 break;     /* ignore others */
  343.         }
  344.     else
  345.     {
  346.       switch ( bframe->cmd & 0xF0 )        /* on command, */
  347.       {
  348.         case 0x10: event = D_RX_RESET; break;
  349.         case 0x20: event = D_RX_RESET_ACK; break;
  350.         case 0x40: event = D_RX_DATA; break;
  351.         case 0x50: event = D_RX_ACK; break;
  352.         default:
  353.                 printf("$%02X unknown DLC cmd\n",bframe->cmd);
  354.                 return;
  355.                  break;
  356.       }
  357.             /* dispatch event only when dlccb is known */
  358.       dlc_event( event, dlccb, bframe, len );
  359.  
  360.     } /* endif */
  361.  
  362.  
  363. }
  364.  
  365.  
  366. /*************************************************************
  367.         Interface : BLP>dlc
  368. **************************************************************/
  369.  
  370.         /** initiate a dlc link;no parms, no return **/
  371.  
  372. void
  373. dlc_start_cmd( )
  374. {
  375.     dlc_event( D_LSTART, &dlcbs, NULL, 0 ) ;    /* try to start 'er up */
  376. }
  377.  
  378.  
  379.         /* send data on the dlc.  returns TRUE if
  380.            sent ok */
  381.  
  382. int  cdecl dlc_data_cmd( data, len )
  383. byte *data;
  384. word len;
  385. {
  386.             /* vars needed to build and add to linked list */
  387.     struct    dl_data_struct *newpacket, *ptr;
  388.     struct    dlccb_struct *dlccb;
  389.  
  390.     dlccb = &dlcbs;        /* init for only dlcb */
  391.  
  392.     if ( dlccb->outstanding < DLC_MAX_OUTSTANDING /*if able to pktz more */
  393.       && dlccb->dlc_state >= DLDATA             /* and in a data state */
  394.       && ( newpacket = (struct dl_data_struct *)
  395.                             malloc(sizeof(struct dl_data_struct)) ) )
  396.             /* and able to allocate then */
  397.     {
  398.         newpacket->len = len ;        /* set up len field */
  399.         memcpy(newpacket->data,data,len);    /* set up data */
  400.         newpacket->next = NULL ;    /* init link field */
  401.  
  402.             /* now add to tail of linked list */
  403.         ptr = &dlccb->dl_next ;    /*1st, ptt to hdr dummy struct */
  404.         while ( ptr->next )           /* while not at end of list */
  405.             ptr = ptr->next ;    /* traverse */
  406.  
  407.             /*now merely put ptr to new packet at end of list link*/
  408.         ptr->next = newpacket;
  409.         dlccb->outstanding++;
  410.  
  411.             /* signal new data */
  412.         dlc_event( D_Q_DATA, dlccb, NULL, 0);
  413.  
  414.         return( TRUE );
  415.     } else  return (FALSE);
  416.  
  417. }
  418.  
  419.  
  420. /*************************************************************
  421.         Interface : dlc>blp
  422. **************************************************************/
  423.  
  424.         /* variable - hold dlccb pointers for each channel */
  425.  
  426.         /*** should return TRUE if able to accept data ***/
  427. int cdecl dlc_data_handler( data, len )
  428. byte *data;
  429. word len;
  430. {
  431.     dlc_in_handler( (struct bframe_struct *) data, len);
  432.         /* ship it to BLP */
  433.     return( TRUE );        /* always return true in this intfc */
  434. }
  435.  
  436.  
  437.                     /* get state tables */
  438. #include    "dlctables.c"
  439.